package com.alibaba.citrus.cr.sales.plan.facade.service.salesplan.audit;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.audit.SalesPlanAuditTaskWriteService;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.audit.SalesPlanAuditWriteService;
import com.alibaba.citrus.cr.sales.plan.functions.salesplan.audit.SalesPlanAuditTaskEntity;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.cr.sales.plan.repository.WxAppletRepository;
import com.alibaba.citrus.cr.sales.plan.repository.request.MessageChannelQueryRequest;
import com.alibaba.citrus.cr.sales.plan.repository.request.MessageTemplatePageQueryRequest;
import com.alibaba.citrus.cr.sales.plan.repository.request.SubWxTempInfoUserQueryRequest;
import com.alibaba.citrus.cr.sales.plan.repository.request.WxAppletMessageSendRequest;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanAuditTaskSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.cz.base.tool.UUIDUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.MessageChannelResponse;
import com.epoch.app.bcorder.model.dto.MessageTemplateResponse;
import com.epoch.app.bcorder.model.dto.WcAppletSubInfoResponse;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author:suqing.tjf
 * @date:2021/9/16
 */
@Service
public class SalesPlanAuditTaskWriteServiceImpl implements SalesPlanAuditTaskWriteService {

    private final static Log log = Log.getLogger(SalesPlanAuditWriteService.class);

    @Resource
    private WxAppletRepository wxAppletRepository;

    @Resource
    private SalesPlanRepository salesPlanRepository;

    private final String SALES_PLAN_AUDIT_EVENT_CODE = "SALES_PLAN_AUDIT";

    private final static String USER_PREFIX_1 = "user:CZ_";

    private final Integer DEFAULT_PAGE_SIZE = 200;

    @Override
    @FacadeInvoker
    public Result<String> syncSalesPlanAuditTask(SalesPlanAuditTaskSDO salesPlanAuditTaskSDO) {
        SalesPlanAuditTaskEntity salesPlanAuditEntity = SalesPlanAuditTaskEntity.of(salesPlanAuditTaskSDO);
        String salesPlanAuditId = salesPlanAuditEntity.save();
        // 发送消息
        sendWxAppletAuditMessage(salesPlanAuditTaskSDO);
        return Result.success(salesPlanAuditId);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> updateSalesPlanAuditTaskStatus(SalesPlanAuditTaskSDO salesPlanAuditTaskSDO) {
        SalesPlanAuditTaskEntity salesPlanAuditEntity = SalesPlanAuditTaskEntity.of(salesPlanAuditTaskSDO);
        Boolean edit = salesPlanAuditEntity.updateByNonId();
        return Result.success(edit);
    }

    private void sendWxAppletAuditMessage(SalesPlanAuditTaskSDO auditTaskSDO) {
        if (StringUtils.isBlank(BcOrderConstants.WX_APP_ID())) {
            log.warn("未配置小程序id");
            return;
        }
        // 微信消息是弱依赖，不阻断主流程
        try {
            // 月度计划
            SalesPlanSDO salesPlanSDO = fetchSalesPlanSDO(auditTaskSDO.getPlanId());
            if (null == salesPlanSDO) {
                log.warn("月度计划:{}不存在", auditTaskSDO.getPlanId());
                return;
            }
            // 获取消息渠道信息
            MessageChannelResponse channelResponse = fetchMessageChannel(BcOrderConstants.WX_APP_ID());
            if (null == channelResponse) {
                log.warn("消息渠道未配置");
                return;
            }
            // 获取微信模板
            List<MessageTemplateResponse> messageTemplateResponses = fetchMessageTemplate(channelResponse.getId());
            if (CollectionUtils.isEmpty(messageTemplateResponses)) {
                log.warn("消息渠道中未配置对应事件微信模板");
                return;
            }
            // 发送微信消息
            sendWxMessage(messageTemplateResponses.get(0), auditTaskSDO, salesPlanSDO);
        } catch (Exception e) {
            log.error("SalesPlanAuditTaskWriteServiceImpl#syncSalesPlanAuditTask_fail " + "发送微信小程序消息发生异常:", e);
        }
    }

    private MessageChannelResponse fetchMessageChannel(String appId) {
        MessageChannelQueryRequest queryRequest = new MessageChannelQueryRequest();
        queryRequest.setType(2);
        queryRequest.setStatus(1);
        queryRequest.setRemoteMessageChannelId(appId);
        return wxAppletRepository.queryMessageChannel(queryRequest);
    }

    private List<MessageTemplateResponse> fetchMessageTemplate(String channelId) {
        MessageTemplatePageQueryRequest pageQueryRequest = new MessageTemplatePageQueryRequest();
        pageQueryRequest.setEventCode(SALES_PLAN_AUDIT_EVENT_CODE);
        pageQueryRequest.setChannelType(2);
        pageQueryRequest.setChannelId(channelId);
        pageQueryRequest.setStatus(1);
        pageQueryRequest.setStart(0);
        pageQueryRequest.setLimit(1);
        return wxAppletRepository.pageQueryMessageTemplate(pageQueryRequest);
    }

    private void sendWxMessage(MessageTemplateResponse response, SalesPlanAuditTaskSDO auditTaskSDO, SalesPlanSDO salesPlanSDO) {
        JSONArray jsonArray = JSON.parseArray(auditTaskSDO.getAssignees());
        if (null == jsonArray) {
            return;
        }
        Map<String,String> auditMap = jsonArray.stream().map(id -> StringUtils.replace(String.valueOf(id), USER_PREFIX_1,"")).collect(Collectors.toMap(s -> s, s -> s));
        if (MapUtils.isEmpty(auditMap)) {
            return;
        }
        int page = 1;
        PageResult<List<WcAppletSubInfoResponse>> pageResult = fetchWcAppletSubUserList(response.getChannelId(), response.getChannelTemplateId(), page);
        while (null != pageResult) {
            pageResult.getContent().forEach(wcAppletSubInfoResponse -> {
                doSendWxMessage(wcAppletSubInfoResponse, auditMap, salesPlanSDO);
            });
            if (pageResult.getContent().size() < DEFAULT_PAGE_SIZE) {
                // 已经是最后一页
                break;
            }
            pageResult = fetchWcAppletSubUserList(response.getChannelId(), response.getChannelTemplateId(), ++page);
        }
    }

    private void doSendWxMessage(WcAppletSubInfoResponse response, Map<String, String> auditMap, SalesPlanSDO salesPlanSDO) {
        if (MapUtils.isEmpty(response.getFeatures())) {
            return;
        }
        String employeeId = response.getFeatures().get("employeeId");
        if (StringUtils.isBlank(employeeId)) {
            return;
        }
        if (null == auditMap.get(employeeId)) {
            log.warn("用户:{}没有订阅微信模板消息", employeeId);
            return;
        }
        if (response.getCount() < 1) {
            log.warn("用户:{}已经没有订阅次数了", employeeId);
            return;
        }
        WxAppletMessageSendRequest sendRequest = new WxAppletMessageSendRequest();
        sendRequest.setBizType("salesPlanAudit");
        sendRequest.setBizId(UUIDUtil.newWithoutMinus());
        sendRequest.setEventCode(SALES_PLAN_AUDIT_EVENT_CODE);
        sendRequest.setTargetType(2);
        // 如果能取到openId，则不用填写
        sendRequest.setTargetId(employeeId);
        Map<String, String> params = Maps.newHashMap();
        buildParam(params, salesPlanSDO);
        sendRequest.setParams(params);
        if (!wxAppletRepository.sendWxAppletMessage(sendRequest)) {
            log.error("发送微信消息失败");
        }
    }

    private void buildParam(Map<String, String> params, SalesPlanSDO salesPlanSDO) {
        String planTime = DateUtils.stampToDate(salesPlanSDO.getPlanTime());
        try {
            salesPlanSDO.setFormatPlanTime(DateUtils.formatPlanTime(planTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
        params.put("planId", String.valueOf(salesPlanSDO.getId()));
        params.put("salesPlanName", salesPlanSDO.getFormatPlanTime());
    }

    private PageResult<List<WcAppletSubInfoResponse>> fetchWcAppletSubUserList(String channelId, String templateId, int i) {
        SubWxTempInfoUserQueryRequest queryRequest = new SubWxTempInfoUserQueryRequest();
        queryRequest.setTemplateId(templateId);
        queryRequest.setChannelId(channelId);
        queryRequest.setPage(i);
        queryRequest.setSize(DEFAULT_PAGE_SIZE);
        PageResult<List<WcAppletSubInfoResponse>> pageResult = wxAppletRepository.queryWcAppletSubUserList(queryRequest);
        if (null == pageResult || CollectionUtils.isEmpty(pageResult.getContent())) {
            return null;
        }
        return pageResult;
    }

    private SalesPlanSDO fetchSalesPlanSDO(String planId) {
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(planId);
        return salesPlanRepository.load(querySalesPlanRequest);
    }
}
